#pragma once
#include<iostream>
#include<string>
#include<sys/time.h>
#include<atomic> //c++11中提供的计数器
#include<sys/stat.h>
#include<unistd.h>
#include<sys/types.h>
#include<fstream>
#include<boost/algorithm/string.hpp>

namespace ns_util
{
    using namespace ns_util;
    const std::string temp_path="./temp/";
    class PathUtil
    {
        public:
        static std::string AddSuffix(const std::string& file_name,const std::string& suffix)
        {
            std::string path_name=temp_path;
            path_name+=file_name;
            path_name+=suffix;
            return path_name;
        }

        //编译时，需要的临时文件
        //构建源文件路径名+后缀的完整文件名
        static std::string Src(const std::string& file_name)
        {
            return AddSuffix(file_name,".cpp");
        }
        //构建可执行程序的完整路径+后缀名(.exe)
        static std::string Exe(const std::string& file_name)
        {
            return AddSuffix(file_name,".exe");
        }
          //构建编译错误的文件路径名+后缀的完整文件名
           static std::string CompileError(const std::string& file_name)
        {
            return AddSuffix(file_name,".compilr_error");
        }
     
        //运行时需要的临时文件
        //构建该程序对应的标准输入完整路径+后缀名
         static std::string Stdin(const std::string& file_name)
        {
            return AddSuffix(file_name,".stdin");
        }
        //构建该程序对应的标准输出完整路径+后缀名
         static std::string Stdout(const std::string& file_name)
        {
            return AddSuffix(file_name,".stdout");
        }
           //构建该程序对应的标准错误完整路径+后缀名
        static std::string Stderr(const std::string& file_name)
        {
            return AddSuffix(file_name,".stderr");
        }
    };

      class TimeUtil
    {
        public:
        static std::string GetTimeStamp()
        {
            struct timeval _time;
          gettimeofday(&_time,nullptr);
          return std::to_string(_time.tv_sec);
        } 

        //获得毫秒级别的时间戳
        static std::string GetTimeMs()
        {
            struct timeval _time;
            gettimeofday(&_time,nullptr);
            return std::to_string(_time.tv_sec*1000+_time.tv_usec/1000);
        }
    };

    
    class FileUtil
    {
      public:
      static bool IsFileExists(const std::string& path_name)
      {
          struct stat st;//stat函数的第二个参数是一个stat的结构体
          if(stat(path_name.c_str(),&st)==0)
          {
              //获取文件属性成功，说明文件已经存在,返回的是0，失败返回的是-1
              return true;
          }
          return false;
      }

      static std::string UniqueFileName()
      {
        static std::atomic_uint id(0);
        ++id;
        //C++11中提供的计数器,因为每一次调用都会重新都开始，所以定义为static
         std::string ms=TimeUtil::GetTimeMs();
         std::string uniq_id=std::to_string(id);
         return ms+"_"+uniq_id; 
      }

      static bool WriteFile(const std::string& target,std::string& code)
      {
        std::ofstream out(target);
        if(!out.is_open())
        {
            return false;
        }
        out.write(code.c_str(),code.size());
        out.close();
        return true;
      }

      static bool ReadFile(const std::string& target,std::string *content,bool keep=false)
      {
          (*content).clear();
        std::ifstream in(target);
        if(!in.is_open())
        {
            return false;
        }
        std::string line;
        while(std::getline(in,line)) 
        {
          (*content)+=line;
          (*content)+=(keep?"\n":""); //getline不保存'\n'；所以当我们要保留'\n'
                         //就传TRUE过来；          
        }
        in.close();
        return true;
      }

    };

  class StringUtil
  {
      public:
      static bool SplitString(std::string target,std::vector<std::string>* out,const std::string sep)
      {
         boost::split((*out),target,boost::is_any_of(sep),boost::token_compress_on);
      }
  };

}